/***************************************************************************
 *   Copyright (C) 2009 by Jason Power                                     *
 *   power.jg@gmail.com                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <QtGui>

#include <openbabel/mol.h>

#include "origindbconvert.h"
#include "molecule.h"
#include "element.h"
#include "molscene.h"

using namespace OpenBabel;

OBMol* molsKetch::convertToMol(MolScene * scene)
{
//     QMessageBox::warning(this,tr(PROGRAM_NAME),tr("Saving is only partially implemented. You may lose data if you overwrite an existing file."),QMessageBox::Ok,QMessageBox::Ok);

    // Create the output molecule
    OBMol* obmol = new OBMol;
    QHash<Atom*,OpenBabel::OBAtom*> hash;
    
    int num = 0;
    // Add all molecules on the scene
    foreach(QGraphicsItem* item, scene->items())
    {
    if (item->type() == Molecule::Type)
	{
	Molecule* mol = dynamic_cast<Molecule*>(item);

	hash.clear();

	obmol->BeginModify();
    //                 obmol->ReserveAtoms(mol->countAtoms());
	foreach (Atom* atom, mol->atoms())
	    {
	    OpenBabel::OBAtom* obatom = obmol->NewAtom();
    //                 Atom* atom = mol->atom(j);
	    obatom->SetVector(atom->scenePos().x()/40,atom->scenePos().y()/40,0);
	    std::string element = atom->element().toStdString();
    //                 obatom->SetType(element);
	    obatom->SetAtomicNum(molsKetch::symbol2number(atom->element()));
    //                 obmol->AddAtom(*obatom);
	    hash.insert(atom,obatom);
    //                 cerr << hash.count() << "\n";
	    }
	foreach (Bond* bond, mol->bonds())
	    {
    //                 Bond* bond = mol->bonds[j];
	    Atom* a1 = bond->firstAtom();
	    Atom* a2 = bond->lastAtom();

	    OBAtom* oba1 = hash.value(a1);
	    OBAtom* oba2 = hash.value(a2);

	    OpenBabel::OBBond* obbond = new OpenBabel::OBBond();
    //                 OBBond* obbond = obmol->NewBond();

	    // Set identifier
    //                 obbond->SetIdx(j);

	    // Set bondorder
	    obbond->SetBO(bond->bondOrder());

	    // Setting bondtype
	    switch (bond->bondType())
		{
		case Bond::Up:
		obbond->SetWedge();
		case Bond::UpR:
		obbond->SetBegin(oba2);
		obbond->SetEnd(oba1);
		obbond->SetWedge();
		break;
		case Bond::Down:
		obbond->SetHash();
		case Bond::DownR:
		obbond->SetBegin(oba2);
		obbond->SetEnd(oba1);
		obbond->SetHash();
		break;
		default:
		obbond->SetBegin(oba1);
		obbond->SetEnd(oba2);
		}

	    // Adding the bond
    //                 obmol->AddBond(oba1->GetIdx(),oba2->GetIdx(),bond->getOrder());

	    obmol->AddBond(*obbond);

	    }
	obmol->EndModify();
	
	num++;
	}
    }
    if (num>0)
	return obmol;
    else
    {
	delete obmol;
	return NULL;
    }

}


Molecule* molsKetch::convertFromMol(OBMol* obmol)
{
    // Create a new molecule
    Molecule* mol = new Molecule();
    mol->setPos(QPointF(0,0));
//         cerr << "mol " << "x: " << mol->pos().x() << " y: " << mol->pos().y() << "\n";

    // Initialize normalization factor
//       qreal factor = 1;
    // molfile.GetInternalCoord(0,0,0);

    // Add atoms one-by-ons
    for (unsigned int i = 1; i <= obmol->NumAtoms();i++)
// 	FOR_ATOMS_OF_MOL(obatom,obmol)
    {
	OpenBabel::OBAtom *obatom = obmol->GetAtom(i);
	//  			scene->addRect(QRectF(atom->GetX(),atom->GetY(),5,5));
	Atom* atom = mol->addAtom(molsKetch::number2symbol(obatom->GetAtomicNum()),QPointF(obatom->x()*40,obatom->y()*40));

    }

    // Add bonds one-by-one
    /// Mind the numbering!
    for (unsigned int i = 0; i < obmol->NumBonds();i++)
// 	FOR_BONDS_OF_MOL(obbond,obmol)
    {
	// Loading the OpenBabel objects
	OpenBabel::OBBond *obbond = obmol->GetBond(i);
	OBAtom *a1 = obbond->GetBeginAtom();
	OBAtom *a2 = obbond->GetEndAtom();

	// Creating their internal counterparts
	Atom* atomA = mol->atomAt(QPointF(a1->x()*40,a1->y()*40));
	Atom* atomB = mol->atomAt(QPointF(a2->x()*40,a2->y()*40));
	Bond* bond  = mol->addBond(atomA,atomB,obbond->GetBondOrder());

	// Set special bond types
	if (obbond->IsWedge()) bond->setType( Bond::Up );
	if (obbond->IsHash()) bond->setType( Bond::Down );
//             if (obbond->IsUp()) bond->setType( Bond::Up );
//             if (obbond->IsDown()) bond->setType( Bond::Down );
	// if (obbond->IsHash()) bond->setType( Bond::Dot );

	// Normalizing
//             factor = scene->getBondLength()/obbond->GetLength();
    }

    // // Normalizing molecule
    // mol->scale(factor,factor);
    // mol->setAtomSize(LABEL_SIZE/factor);

    return mol;
}